import logging
import socket
import threading
import sys
from optparse import OptionParser

# ------------------------------------------------------- #
# GLOBALS

options = None
logger = None

socket_client = None
socket_srv_clients = None

# ------------------------------------------------------- #
# Client thread

def Server_Client_Thread(address,sock):

    logger.info("SERVER: %s connected on local port %s",address[0],address[1])
    socket_srv_clients.append(sock)

    while True:
        data = sock.recv(1024)
        if data is None or len(data) == 0:
            break

        logger.debug("SERVER: data from %s[%s]: %s", address[0], address[1], data)

        # Broadcast to clients
        if socket_client is not None:
            socket_client.sendall(data)

    logger.info("SERVER: %s disconnected from local port %s",address[0],address[1])
    socket_srv_clients.remove(sock)
    sock.close()

def Client_Thread(clsock):
    logger.info("CLIENT: running")

    while True:
        data = clsock.recv(1024)
        if data is None:
            logger.info("CLIENT: disconnected from %s:%s",options.clientaddr,options.clientport)
            break

        logger.debug("CLIENT: data: %s", data)

        # Throw data to all other clients
        for srvcl in socket_srv_clients:
            srvcl.sendall(data)

    # Cleanup
    logger.info("CLIENT: stopped")
    clsock.close()

# Server thread
def Server_Thread(srvsock):

    logger.info("SERVER: running")

    while True:
        (client,address) = srvsock.accept()

        # Launch new client thread
        thread = threading.Thread(target=Server_Client_Thread,args=(address,client,))
        thread.daemon = True
        thread.start()

    logger.info("SERVER: stopped")
    srvsock.close()

# ------------------------------------------------------- #

def config_logger():
    global logger
    level = logging.WARNING

    if options.verbose:
        level = logging.DEBUG

    logger = logging.Logger(None)
    logger.addHandler(logging.StreamHandler())
    logger.setLevel(level)

def config_parser():
    global options
    parser = OptionParser(usage="%s [options]")

    parser.add_option(\
        "-s", "--server-port",\
        help = "set TCP server port",\
        dest = "serverport",
        type = "int",
        default = "3000")

    parser.add_option(\
        "-a", "--client-addr",\
        help = "set the address for the TCP client to connect to",\
        dest = "clientaddr",\
        type = "string",
        default=None)

    parser.add_option(\
        "-p" ,"--client-port",\
        help = "set the port for the TCP client to connect trough",\
        dest = "clientport",\
        type = "int",
        default=0)

    parser.add_option(\
        "-v", "--verbose",\
        help="enable verbose output",\
        dest="verbose",\
        action="store_true",\
        default=False)

    (options,args) = parser.parse_args()



if __name__ == "__main__":
    config_parser()
    config_logger()

    # Attempt to connect to the specified server
    if options.clientaddr != None:
        logger.info("Connecting to server %s:%s",options.clientaddr,options.clientport)
        try:
            sock = socket.socket()
            sock.connect((options.clientaddr,options.clientport))
        except:
            logger.error("Could not connect to %s:%s",options.clientaddr,options.clientport)
            exit()

        global socket_client
        socket_client = sock
        thread = threading.Thread(target=Client_Thread,args=(sock,))
        thread.start()
    else:
        logger.info("Note: not connecting to another server")

    # Start TCP/IP server
    logger.info("Starting TCP server at port %s",options.serverport)
    socket_srv_clients = []
    try:
        srvsocket = socket.socket()
        srvsocket.bind(("127.0.0.1",options.serverport))
        srvsocket.listen(5)

        thread = threading.Thread(target=Server_Thread, args=(srvsocket,))
        thread.daemon = True
        thread.start()
    except:
        logger.error("SERVER: could not start server on port %s",options.serverport)

    # Process input
    for line in sys.stdin.read():
        for sock in socket_srv_clients:
            sock.sendall(line)
